/**
 * @author yu
 * @date 2024/01/12
 * @description 用于解析串口数据
 * @param {string} 串口数据 eg: 'F2F2F008000101000002010a077E'
 * @returns {object} eg: { key: 'xx', value: '' } key: 串口 code，value 是相对应的数据
 *
 * @content 注意事项： 验证校验和，起始码 结束码，如果不对，不进行数据校验
 * @content 注意事项： 需要算一下校验和，和取低位. eg: 0a01 => 01
 */
import { showToast } from 'vant'
import { verifySum } from '@/utils/utils'

const model = [
  {
    name: 'germ', // 微生物
    len: 1,
    code: '01'
  },
  {
    name: 'oxygen', // 含氧量
    len: 1,
    code: '02'
  },
  {
    name: 'tvoc', // tvoc
    len: 2,
    code: '03'
  },
  {
    name: 'temp', // 环境温度
    len: 1,
    code: '04'
  },
  {
    name: 'humidity', // 环境湿度
    len: 1,
    code: '05'
  },
  {
    name: 'pm', // pm2.5
    len: 2,
    code: '06'
  },
  {
    name: 'sensor', // 传感器
    len: 1,
    code: '07'
  },
  {
    name: 'kpa', // 压差
    len: 1,
    code: '08'
  },
  {
    name: 'dischargeAir', // 排风
    len: 1,
    code: '09'
  },
  {
    name: 'blowAir', // 送风
    len: 1,
    code: '0a'
  },
  {
    name: 'time', // 定时
    len: 2,
    code: '0b'
  },
  {
    name: 'mode', // 模式
    len: 1,
    code: '0c'
  },
  {
    name: 'pdp', // 等离子
    len: 1,
    code: '0d'
  },
  {
    name: 'offOn', // 关机
    len: 1,
    code: '0e'
  },
  {
    name: 'anion', // 负离子
    len: 1,
    code: '0f'
  },
  {
    name: 'control', // 程控
    len: 100,
    code: '10'
  },
  {
    name: 'heating', // 电辅热
    len: 1,
    code: '11'
  },
  {
    name: 'freeze', // 电机防冻
    len: 1,
    code: '12'
  },
  {
    name: 'disinfect', // 排风消毒
    len: 1,
    code: '13'
  },
  {
    name: 'pdpTime', // 等离子运行时间
    len: 2,
    code: '14'
  },
  {
    name: 'dischargeAirTime', // 排风运行时间
    len: 2,
    code: '15'
  },
  {
    name: 'blowAirTime', // 送风运行时间
    len: 2,
    code: '16'
  },
  {
    name: 'lowEffectTime', // 运行时间（初效滤网）
    len: 2,
    code: '17'
  },
  {
    name: 'hightEffectTime', // 运行时间（高效滤网）
    len: 2,
    code: '18'
  },
  {
    name: 'clock', // 时钟
    len: 6,
    code: '19'
  },
  {
    name: 'fault', // 故障
    len: 1,
    code: '1a'
  },
  {
    name: 'acMode', // 空调模式
    len: 1,
    code: '1b'
  },
  {
    name: 'acTemp', // 空调温度
    len: 1,
    code: '1c'
  },
  {
    name: 'acHumidity', // 空调湿度
    len: 1,
    code: '1d'
  },
  {
    name: 'acStatus', // 空调状态
    len: 1,
    code: '1e'
  },
  {
    name: 'acMain', // 空调主机
    len: 1,
    code: '1f'
  },
  {
    name: 'unitMode', // 机组模式
    len: 1,
    code: '20'
  },
  {
    name: 'unitHFF', // 机组回风阀
    len: 1,
    code: '21'
  },
  {
    name: 'unitXFF', // 机组新风阀
    len: 1,
    code: '22'
  },
  {
    name: 'unitPFF', // 机组排风阀
    len: 1,
    code: '23'
  },
  {
    name: 'unitSFDJ', // 机组送风电机
    len: 1,
    code: '24'
  },
  {
    name: 'unitPFDJ', // 机组排风电机
    len: 1,
    code: '25'
  },
  {
    name: 'unitCXLW', // 机组初效滤网
    len: 1,
    code: '26'
  },
  {
    name: 'unitZXLW', // 机组中效滤网
    len: 1,
    code: '27'
  },
  {
    name: 'unitMain', // 机组主机
    len: 1,
    code: '28'
  },
  {
    name: 'unitXD', // 机组消毒
    len: 1,
    code: '29'
  },
  {
    name: 'unitHFTemp', // 机组回风温度
    len: 1,
    code: '2a'
  },
  {
    name: 'unitHFHumidity', // 机组回风湿度
    len: 1,
    code: '2b'
  },
  {
    name: 'unitSFTemp', // 机组送风温度
    len: 1,
    code: '2c'
  },
  {
    name: 'unitSFHumidity', // 机组送风湿度
    len: 1,
    code: '2d'
  },
  {
    name: 'unitCool', // 机组冷水
    len: 1,
    code: '2e'
  },
  {
    name: 'unitHot', // 机组热水
    len: 1,
    code: '2f'
  },
  {
    name: 'unitHeating', // 机组电加热
    len: 1,
    code: '30'
  },
  {
    name: 'unitHumidifier', // 机组加湿
    len: 1,
    code: '31'
  },
  {
    name: 'unitFault', // 机组空调系统故障
    len: 1,
    code: '32'
  },
  {
    name: 'unitXFTemp', // 机组新风温度
    len: 1,
    code: '33'
  }
]

export function parseData(uartData) {
  console.log('rawData===', uartData)
  let rawData = strConvertToArr(uartData)
  const startCode = 'F2'
  const featureCode = ['F0', 'F3', '02']
  const endCode = '7E'

  console.log('开始校验：：：：：')

  // toUpperCase() 转大写
  if (rawData[0].toUpperCase() !== startCode && rawData[1].toUpperCase() !== startCode) {
    console.log(1)
    showToast('起始码不正确,不能正确解析数据')
    return
  }

  if (!featureCode.includes(rawData[2].toUpperCase())) {
    console.log(2)
    showToast('功能码不正确,不能正确解析数据')
    return
  }

  if (rawData[rawData.length - 1].toUpperCase() !== endCode) {
    console.log(3)
    showToast('结束码不正确,不能正确解析数据')
    return
  }
  // slice() 方法会返回一个新数组，不会改变原数组。
  const sumArr = rawData.slice(2, rawData.length - 2)
  console.log('sumArr====', sumArr)
  const sum = verifySum(sumArr)
  console.log('sum===', sum)
  if (sum.toUpperCase() !== rawData[rawData.length - 2].toUpperCase()) {
    console.log(4)
    showToast('校验和不正确,不能正确解析数据')
    return
  }
  // 去除起始码和结束码，去除校验和，去除功能码
  rawData = rawData.slice(4, rawData.length - 2)
  console.log('rawData>>>>', rawData)
  /**
   * 需要校验起始码，结束码，校验和，如果不一致的话。则不能解析，提示用户
   */

  /**
   * 开始码: F2F2
   * 结束码: 7E
   * 功能码: F0/F3/02
   * 校验和: 除了起始码与结束码外，其余的数据进行和校验（数据累加）
   * 校验和eg: F2 F2 F0 04 00 01 01 02 07 7E => F0 + 04 + 00 + 01 + 01 + 02
   * test: F2F2F01a000101000002010a00030200640004012800050128000602012c007E
   * ['F2', 'F2', 'F0', '1a', '00', '01', '01', '00', '00', '02', '01', '0a', '00', '03', '02', '00', '64', '00', '04', '01', '28', '00', '05', '01', '28', '00', '06', '02', '01', '2c', '00', '7E']
   */

  // 参数对象
  let len = 0
  let params = {}

  for (let i = 0; i < rawData.length; i++) {
    for (let j = 0; j < model.length; j++) {
      let rawVal = ''
      if (rawData[len + 1]) {
        console.log(rawData[len + 1])
        console.log(model[j].code, 'code')
        if (rawData[len + 1].toLowerCase() == model[j].code) {
          console.log('ok====')
          console.log(rawData[len + 2])
          if (rawData[len + 2] == 1) {
            console.log(7777777777)
            // 长度为 1
            rawVal = rawData[len + 3]
            rawVal = parseInt(rawVal, 16)
            params[model[j].name] = rawVal
          } else if (rawData[len + 2] == 2) {
            // 长度为 2
            console.log('999999999')
            rawVal = rawData[len + 3] + rawData[len + 4]
            rawVal = parseInt(rawVal, 16)
            params[model[j].name] = rawVal
          } else if (rawData[len + 2] == 64) {
            console.log('进来了==')
            /**
             * byte0:开关0：关闭 1:开启
             * byte1:星期 bit0~6:星期1~7
             * byte2：开始时 0~23
             * byte3：开始分 0~59
             * byte4:结束时
             * byte5:结束分
             * byte6：等离子 0：关闭 1:开启
             * byte7：负离子 0：关闭 1:开启
             * byte8：排风 0:关闭 1:1档 2:2档 3:3档
             * byte9：送风 0:关闭 1:1档 2:2档 3:3档
             */

            // 长度为 100
            // 获取 10 组全部的数据
            const arr10 = rawData.slice(len + 3, len + 103)
            console.log(arr10)

            // 返回 10 组数据
            const obj = convertArrayToObjectArray(arr10)
            console.log(obj, 'obj===')
            params[model[j].name] = obj
          } else if (rawData[len + 2] == 6) {
            // code值长度为 6
            console.log('66666')
            // 时钟设置
            params[model[j].name] = {
              year: parseInt(rawData[len + 3], 16),
              month: parseInt(rawData[len + 4], 16),
              day: parseInt(rawData[len + 5], 16),
              week: parseInt(rawData[len + 6], 16),
              hour: parseInt(rawData[len + 7], 16),
              minute: parseInt(rawData[len + 8], 16)
            }
          }

          len = len + model[j].len + 3
        }
      }
    }
  }

  console.log('params====', params)
  return params
}

/**
 * Converts an array of 100 elements into an array of 10 objects with 10 elements each.
 *  // EG:
    // const egArr = [
    //   {
    //     switch: 1,
    //     week: 1,
    //     startHour: 10,
    //     startMin: 20,
    //     endHour: 20,
    //     endMin: 30,
    //     anion: 1, // 负离子
    //     pdp: 1, // 等离子
    //     exhaust: 1,
    //     blowing: 1
    //   }
    // ]
 * @param {Array} array 包含 100 个元素的数组
 * @returns {Array<Object>} 返回 10 组数组对象
 */
function convertArrayToObjectArray(array) {
  console.log(array, 'array====')
  const objectArray = []
  // parseInt(hex, 16) 16 进制转 10 进制
  for (let i = 0; i < array.length; i += 10) {
    const object = {
      switch: parseInt(array[i + 0], 16) ? true : false,
      week: hexToBit(array[i + 1]),
      weekStr: binaryToWeekdays(array[i + 1]),
      startHour: parseInt(array[i + 2], 16),
      startMin: parseInt(array[i + 3], 16),
      endHour: parseInt(array[i + 4], 16),
      endMin: parseInt(array[i + 5], 16),
      anion: parseInt(array[i + 6], 16),
      pdp: parseInt(array[i + 7], 16),
      exhaust: parseInt(array[i + 8], 16), // 排风
      blowing: parseInt(array[i + 9], 16) // 送风
    }
    objectArray.push(object)
  }

  return objectArray
}

/**
 * @description 将十六进制字符串转换为数组,
 * @param {string} hexString
 * @returns {Array}
 */
const strConvertToArr = hexString => {
  let arr = []
  for (let i = 0; i < hexString.length; i += 2) {
    arr.push(hexString.substring(i, i + 2))
  }

  return arr
}

/**
 * @description 获取周数组 周只占了一个字节，有 8 个 bit，bit0~6 表示周一到周日
 * @param {string} hex
 * @returns {string} 返回包含的星期字符串
 */
export const binaryToWeekdays = hex => {
  const weekdays = ['', '周日', '周六', '周五', '周四', '周三', '周二', '周一']
  const binary = hexToBit(hex)
  let result = ''
  for (let i = 0; i < binary.length; i++) {
    if (binary[i] === '1') {
      result += weekdays[i] + ' '
    }
  }

  result.split(' ').reverse().join(' ')
  // result.trim()
  return result
}

/**
 * @description 获取周数组 周只占了一个字节，有 8 个 bit，bit0~6 表示周一到周日
 * @param {string}  hex 16进制的数值
 * @returns {array} 返回包含的星期
 */
export const hexToBit = hex => {
  const decimal = parseInt(hex, 16)
  // 把 16 进制的字符串转换成二进制
  const binary = decimal.toString(2).padStart(8, '0')
  return binary
}
